<?php

class TestExampleMapper extends PHPUnitTest {

    /**
     * Variables
     */

    /**
     * @var MySqliQueryExecutor
     */
    private $queryExecutor;

    /**
     * @var ExampleMapper
     */
    private $exampleMapper;

    /**
     * Fixtures
     */

    protected function setUp() {
        $this->queryExecutor = new MySqliQueryExecutor();
        $this->exampleMapper = new ExampleMapper();
        $this->createExampleTable();
        $this->fillExampleTable();
    }

    protected function tearDown() {
        $this->dropExampleTable();
        unset($this->queryExecutor);
        unset($this->exampleMapper);
    }

    /**
     * Tests
     */

    public function testExampleMapperGetById() {
        $example = $this->exampleMapper->getById('1');

        $this->assertNotNull($example);
        $this->assertInstanceOf('Example', $example);
        $this->assertEquals(1, $example->id);
        $this->assertEquals('ABC', $example->data);
    }

    public function testExampleMapperGetAll() {
        $examples = $this->exampleMapper->getAll();

        $this->assertNotNull($examples);
        $this->assertEquals(3, count($examples));
        $this->assertInstanceOf('Example', $examples[0]);
        $this->assertInstanceOf('Example', $examples[1]);
        $this->assertInstanceOf('Example', $examples[2]);
        $this->assertEquals(1, $examples[0]->id);
        $this->assertEquals('ABC', $examples[0]->data);
        $this->assertEquals(2, $examples[1]->id);
        $this->assertEquals('XYZ', $examples[1]->data);
        $this->assertEquals(3, $examples[2]->id);
        $this->assertEquals('XYZ', $examples[2]->data);
    }

    public function testExampleMapperGetByConditions() {
        $examples = $this->exampleMapper->getByConditions(array(new Criteria('data', Criteria::EQUAL, 'XYZ')));

        $this->assertNotNull($examples);
        $this->assertEquals(2, count($examples));
        $this->assertInstanceOf('Example', $examples[0]);
        $this->assertInstanceOf('Example', $examples[1]);
        $this->assertEquals(2, $examples[0]->id);
        $this->assertEquals('XYZ', $examples[0]->data);
        $this->assertEquals(3, $examples[1]->id);
        $this->assertEquals('XYZ', $examples[1]->data);
    }

    public function testExampleMapperGetFirstByConditions() {
        $example = $this->exampleMapper->getFirstByConditions(array(new Criteria('data', Criteria::EQUAL, 'XYZ')));

        $this->assertNotNull($example);
        $this->assertInstanceOf('Example', $example);
        $this->assertEquals(2, $example->id);
        $this->assertEquals('XYZ', $example->data);
    }

    public function testExampleMapperDeleteAll() {
        $this->exampleMapper->deleteAll();
        $examples = $this->exampleMapper->getAll();

        $this->assertEmpty($examples);
    }

    public function testExampleMapperTruncate() {
        $this->exampleMapper->truncate();
        $examples = $this->exampleMapper->getAll();

        $this->assertEmpty($examples);
    }

    public function testExampleMapperDelete() {
        $exampleToDelete = $this->exampleMapper->getById('2');

        $this->exampleMapper->delete($exampleToDelete);

        $examples = $this->exampleMapper->getAll();
        $this->assertEquals(2, count($examples));
        $this->assertEquals(1, $examples[0]->id);
        $this->assertEquals('ABC', $examples[0]->data);
        $this->assertEquals(3, $examples[1]->id);
        $this->assertEquals('XYZ', $examples[1]->data);
    }

    public function testExampleMapperDeleteById() {
        $exampleToDelete = $this->exampleMapper->getById('2');

        $this->exampleMapper->deletebyId($exampleToDelete->id);

        $examples = $this->exampleMapper->getAll();
        $this->assertEquals(2, count($examples));
        $this->assertEquals(1, $examples[0]->id);
        $this->assertEquals('ABC', $examples[0]->data);
        $this->assertEquals(3, $examples[1]->id);
        $this->assertEquals('XYZ', $examples[1]->data);
    }

    public function testExampleMapperDeleteByCondition() {
        $this->exampleMapper->deletebyCondition(new Criteria('data', Criteria::EQUAL, 'XYZ'));

        $examples = $this->exampleMapper->getAll();
        $this->assertEquals(1, count($examples));
        $this->assertEquals(1, $examples[0]->id);
        $this->assertEquals('ABC', $examples[0]->data);
    }

    public function testExampleMapperDeleteByConditions() {
        $this->exampleMapper->deletebyConditions(array(new Criteria('data', Criteria::EQUAL, 'XYZ'), new Criteria('id', Criteria::EQUAL, '2')));

        $examples = $this->exampleMapper->getAll();
        $this->assertEquals(2, count($examples));
        $this->assertEquals(1, $examples[0]->id);
        $this->assertEquals('ABC', $examples[0]->data);
        $this->assertEquals(3, $examples[1]->id);
        $this->assertEquals('XYZ', $examples[1]->data);
    }

    public function testExampleMapperUpdate() {
        $example = $this->exampleMapper->getById('1');
        $example->data = 'PQR';

        $this->exampleMapper->update($example);

        $example = $this->exampleMapper->getById('1');
        $this->assertEquals('PQR', $example->data);
    }

    public function testUpdateByCondition() {
        $fieldsToUpdate = array('data' => 'QWE');
        $dataCondition = new Criteria('data', Criteria::EQUAL, 'XYZ');

        $this->exampleMapper->updateByCondition($fieldsToUpdate, $dataCondition);

        $examples = $this->exampleMapper->getAll();

        $this->assertEquals(1, $examples[0]->id);
        $this->assertEquals('ABC', $examples[0]->data);
        $this->assertEquals(2, $examples[1]->id);
        $this->assertEquals('QWE', $examples[1]->data);
        $this->assertEquals(3, $examples[2]->id);
        $this->assertEquals('QWE', $examples[2]->data);
    }

    public function testUpdateByConditions() {
        $fieldsToUpdate = array('data' => 'QWE');
        $dataCondition = new Criteria('data', Criteria::EQUAL, 'XYZ');
        $idCondition = new Criteria('id', Criteria::EQUAL, '2');
        $this->exampleMapper->updateByConditions($fieldsToUpdate, array($dataCondition, $idCondition));

        $examples = $this->exampleMapper->getAll();

        $this->assertEquals(1, $examples[0]->id);
        $this->assertEquals('ABC', $examples[0]->data);
        $this->assertEquals(2, $examples[1]->id);
        $this->assertEquals('QWE', $examples[1]->data);
        $this->assertEquals(3, $examples[2]->id);
        $this->assertEquals('XYZ', $examples[2]->data);
    }

    public function testExampleInsert() {
        $example = new Example(array('id'=>'4', 'data'=>'QWE'));

        $this->exampleMapper->insert($example);

        $example = $this->exampleMapper->getById('4');
        $this->assertNotNull($example);
        $this->assertEquals('4', $example->id);
        $this->assertEquals('QWE', $example->data);
    }

    /**
     * Helpers
     */

    private function createExampleTable() {
        $query = 'CREATE TABLE example(id INT, data TEXT)';
        $this->queryExecutor->executeQueryString($query);
    }

    private function fillExampleTable() {
        $query = "INSERT INTO example VALUES(1, 'ABC');";
        $this->queryExecutor->executeQueryString($query);
        $query = "INSERT INTO example VALUES(2, 'XYZ');";
        $this->queryExecutor->executeQueryString($query);
        $query = "INSERT INTO example VALUES(3, 'XYZ');";
        $this->queryExecutor->executeQueryString($query);
    }

    private function dropExampleTable() {
        $query = 'DROP TABLE example;';
        $this->queryExecutor->executeQueryString($query);
    }

}